# encoding: utf-8
from app.extensions import log, db
from .models import Menu as MenuObj

from flask_restplus import Resource, fields
from app.extensions.api import Namespace, abort, http_exceptions
from . import parameters, schemas
from config import BaseConfig
from app.modules.common.utils import DbCommit, checkToken
from app.modules.role.models import RoleMenu
from sqlalchemy import distinct
from app.modules.common.schemas import BaseSchema

api = Namespace('menu', description = "The interface for menu operation")  # pylint: disable=invalid-name


@api.route('/')
class Menu(Resource):
    @api.parameters(parameters.MenuParameters())
    @api.response(schemas.MenuSchema(many = False))
    @checkToken
    def get(self, args):
        """
        query menu list or menu info by role_id
        :param args:
        :return:
        """
        log.info("============== start query menus ==============")

        _role_id = None
        if args['role_id'] is not None:
            _role_id = eval(args['role_id'])
            if type(_role_id) is not list:
                _msg = "this _role_id %s is not list" % _role_id
                log.error("============== %s ==============" % _msg)
                return {'success': False, 'msg': _msg}
        log.info("============== query menus , _role_id is %s ==============" % _role_id)
        if _role_id is None or BaseConfig.ROLE_ADMIN_ID in _role_id:
            _menus = MenuObj.query.filter_by(menu_level = 1).all()
            for _menu in _menus:
                _childMenus = MenuObj.query.filter_by(menu_level = 2, parent_menu_id = _menu.menu_id).all()
                _menu.child_menu_list = _childMenus
        else:
            _ids = []
            _menu_ids = db.session.query(distinct(RoleMenu.menu_id)).filter(RoleMenu.role_id.in_(_role_id)).all()
            for _id, in _menu_ids:
                _ids.append(_id)
            _menus = db.session.query(MenuObj).filter(MenuObj.menu_level == 1, MenuObj.menu_id.in_(_ids)).all()
            for _m in _menus:
                _childMenus = db.session.query(MenuObj).filter(MenuObj.menu_level == 2,
                                                               MenuObj.parent_menu_id == _m.menu_id
                                                               , MenuObj.menu_id.in_(_ids)).all()
                _m.child_menu_list = _childMenus

        return {'success': True, 'msg': '', "data": _menus}


@api.route('/add')
class AddMenu(Resource):
    @api.parameters(parameters.MenuAddParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args):
        """
        add a new menu
        :param args:
        :return:
        """
        log.info("============== start add menu ==============")
        _menu_name = args['menu_name']
        _menu_level = args['menu_level']
        _menu_url = args['menu_url']
        _parent_menu_id = args['parent_menu_id']
        _menu_css = args['menu_css']
        from app.modules.common.dbUtil import createId
        _menu = MenuObj(createId('m'), _menu_name, _menu_url, _menu_level, 0, _parent_menu_id, _menu_css)
        log.info("============== add menu %s ==============" % _menu.to_dict())
        db.session.add(_menu)
        return DbCommit()


@api.route('/update')
class UpdateMenu(Resource):
    @api.parameters(parameters.MenuUpdateParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args):
        """
        update menu info
        :param args:
        :return:
        """
        log.info("============== start update menu ==============")
        _menu_id = args['menu_id']
        _menu_name = args['menu_name']
        _menu_url = args['menu_url']
        _menu_status = args['menu_status']
        _menu_css = args['menu_css']
        log.info("============== update menu , menu_id is %s ==============" % _menu_id)
        log.info("============== update menu , menu_name is %s ==============" % _menu_name)
        log.info("============== update menu , menu_url is %s ==============" % _menu_url)
        log.info("============== update menu , menu_status is %s ==============" % _menu_status)
        _menu = MenuObj.query.filter_by(menu_id = _menu_id).first()
        if _menu is None:
            _msg = "update menu ,menu %s is not exist" % _menu_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        else:
            _menu.menu_name = _menu_name
            _menu.menu_url = _menu_url
            _menu.menu_css = _menu_css
            _menu.menu_status = int(_menu_status)
            return DbCommit()


@api.route('/del')
class delMenu(Resource):
    @api.parameters(parameters.MenuDelParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args):
        """
        del menu
        :param args:
        :return:
        """
        log.info("============== start del menu ==============")
        _menu_id = args['menu_id']
        log.info("============== del menu %s ==============" % _menu_id)
        _menu = MenuObj.query.filter_by(menu_id = _menu_id).first()
        if _menu is None:
            _msg = "del menu ,menu %s is not exist" % _menu_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        else:
            _child_list = MenuObj.query.filter_by(parent_menu_id = _menu_id).all()
            if len(_child_list) != 0:
                for _m in _child_list:
                    db.session.delete(_m)
            db.session.delete(_menu)
            return DbCommit()
